<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<script>
		// 下面就是更改后的代码，我们用加粗显示被修改的部分
		function Shape() {
			Shape.prototype.name = 'Shape';
			Shape.prototype.toString = function() {
				return this.name;
			}
		}

		function TwoDShape() {};
		TwoDShape.prototype = Shape.prototype;
		TwoDShape.prototype.constructor = TwoDShape;
		TwoDShape.prototype.name = '2D shape';

		function Triangle(side, height) {
			this.side = side;
			this.height = height;
		}

		Triangle.prototype = TwoDShape.prototype;
		Triangle.prototype.constructor = Triangle;
		Triangle.prototype.name = 'Triangle';
		Triangle.prototype.getArea = function() {
			return this.side * this.height / 2;
		}

		var my = new Triangle(5, 10);
		var my1 = new TwoDShape();
		console.log(my1.name);
		console.log(my.getArea());
		console.log(my.toString());

		// 这样简单的拷贝原型从效率上来说固然会更好一些，但也有他的副作用。由于子对象与父对象指向的是同一个对象，所以一旦子对象对其原型进行了修改，父对象也会随即被改变，甚至所有的继承关系也都是如此。
		Triangle.prototype.name = 'Triangle';
		// 尤其是这句，他对name属性进行了修改，于是Shape.prototype.name也随之改变了，也就是说，当我们再用new Shape()新建对象时，新对象的name属性也会是Triangle
		var s = new Shape();
		console.log(s.name);

		//因而，这种方法虽然效率很高，但是在很多场景下并不适用
	</script>
	<script>
		function Shape() {
			Shape.prototype.name = 'Shape';
			Shape.prototype.toString = function() {
				return this.name;
			}
		}

		function TwoDShape() {};

		var F = function() {};
		F.prototype = Shape.prototype;
		TwoDShape.prototype = new F();
		TwoDShape.prototype.constructor = TwoDShape;

		TwoDShape.prototype.name = '2D shape';

		function Triangle(side, height) {
			this.side = side;
			this.height = height;
		}

		var F = function() {};
		F.prototype = TwoDShape.prototype;
		Triangle.prototype = new F();
		Triangle.prototype.constructor = Triangle;

		Triangle.prototype.name = 'Triangle';
		Triangle.prototype.getArea = function() {
			return this.side * this.height / 2;
		}

		// 下面，我们来创建一个triangle对象，并测试其方法
		var my = new Triangle(5, 10);
		console.log(my.getArea());
		console.log(my.toString());

		// 通过这种方法，我们就可以保持住原型链
		console.log(my.__proto__ === Triangle.prototype);
		console.log(my.__proto__.constructor === Triangle);
		console.log(my.__proto__.__proto__ === TwoDShape.prototype);
		console.log(my.__proto__.__proto__.__proto__.constructor === Shape);

		// 并且父对象的属性不会被子对象所覆盖
		var s = new Shape();
		console.log(s.name);
		console.log('I am a ' + new TwoDShape());

		// 与此同时，该方法也对一种意见提供了支持：将所有要共享的属性与方法添加到原型中，然后只围绕原型构建继承关系。也就是说，这种主张不鼓励将对象的自身属性纳入继承关系，因为自身属性往往随着对象的不同而差别甚大，无法重用
	</script>
</body>
</html>